#include "game.h"
#include <QFile>
#include <QTextStream>
#include <QDebug>
#include <QTimer>
#include <QTime>
#include <QEventLoop>

Game::Game(const QString &fileName)
{
    loadMap(fileName);
    //setMonsterMap();
    loadImage();
}

void Game::loadImage()
{
    emptyImg=QImage(":/images/empty.png");
    heroImg=QImage(":/images/hero.png");
    enemyImg=QImage(":/images/hero.png");
    monsterImg=QImage(":/images/target.png");
    targetImg=QImage(":/images/target.png");
    bombImg=QImage(":/images/bomb.png");
    wallImg=QImage(":/images/wall.png");
    wallImg2=QImage(":/images/box.png");
    fireImg=QImage(":/images/fire.png");
}
void Game::loadMap(const QString &fileName)
{
    QFile inputFile(fileName);
    inputFile.open(QIODevice::ReadOnly);
    QTextStream reader(&inputFile);

    QString line = reader.readLine();
    int j = 0;
    while(!line.isNull()) {
        qDebug("%s",qPrintable(line));
        //qDebug("read one line");
        // 以空格为分隔符号，分割一行数据；
        QStringList strs = line.split(" ");
        for (int i = 0; i < 19; i++) {
            map[i][j] = strs[i];
            if (strs[i]=="T") {
                // 记录目标位置
                target[i][j] = "T";
            } else {
                // 非目标位置记为O
                target[i][j] = "O";
            }
            // 记录hero的初始位置
            if (strs[i]=="H") {
                this->x = i;
                this->y = j;
            }
            // 记录monster的初始位置
            if (strs[i]=="S") {
                this->m1x = i;
                this->m1y = j;
            }

        }
        qDebug("FINISHED1");
        line = reader.readLine();
        j++;
    }
    inputFile.close();
    for(int i=0;i<150;i++)
    {
    //QTime time;
    //time= QTime::currentTime();
    //qsrand(time.msec()+time.second()*1000);
    int xxx=generateRandomInteger(1, 19);
    int yyy=generateRandomInteger(1, 19);
    if ((xxx+1)%2==0||(yyy+1)%2==0){
        if(xxx!=0&&yyy!=0){
            if(xxx!=18&&yyy!=18&&xxx!=19&&yyy!=19){
                map[xxx][yyy]="M";
            }
        }
    }
    }
    map[17][16]="E";
    map[16][17]="E";
    map[17][17]="H";
    map[1][1]="S";
    map[X][Y]="N";

}
void Game::moveLeft(){
    //qDebug("moveLeft");
    int a = x;
    int b = y;
    if (map[a - 1][b]!="W"&&map[a - 1][b]!="M") {
        if (map[a - 1][b]=="B") {
            if (map[a - 2][b]!="B"&& map[a - 2][b]!="W") {
                if (target[a][b]=="T") {
                    map[a - 1][b] = "H";
                    map[a][b] = "T";
                    map[a - 2][b] = "B";
                    x = a - 1;
                } else {
                    map[a - 1][b] = "H";
                    map[a][b] = "E";
                    map[a - 2][b] = "B";
                    x = a - 1;
                }
            }
        } else {
            /*if (target[a][b]=="T") {
                map[a - 1][b] = "H";
                map[a][b] = "T";
                x = a - 1;
            } else {
                map[a - 1][b] = "H";
                map[a][b] = "E";
                x = a - 1;
            }*/
            map[a - 1][b] = "H";
            map[a][b] = "E";
            x = a - 1;
        }
    }
}
void Game::moveRight(){
    //qDebug("moveRight");
    int a = x;
    int b = y;
    if (map[a + 1][b]!="W"&&map[a + 1][b]!="M") {
        if (map[a + 1][b]=="B") {
            if (map[a + 2][b]!="B"&& map[a + 2][b]!="W") {
                if (target[a][b]=="T") {
                    map[a + 1][b] = "H";
                    map[a][b] = "T";
                    map[a + 2][b] = "B";
                    x = a + 1;
                } else {
                    map[a + 1][b] = "H";
                    map[a][b] = "E";
                    map[a + 2][b] = "B";
                    x = a + 1;
                }
            }
        } else {
            /*if (target[a][b]=="T") {
                map[a + 1][b] = "H";
                map[a][b] = "T";
                x = a + 1;
            } else {
                map[a + 1][b] = "H";
                map[a][b] = "E";
                x = a + 1;
            }*/
            map[a + 1][b] = "H";
            map[a][b] = "E";
            x = a + 1;
        }
    }
}
void Game::moveUp(){
    //qDebug("moveUp");
    int a = x;
    int b = y;
    if (map[a][b - 1]!="W"&&map[a][b - 1]!="M") {
        if (map[a][b - 1]=="B") {
            if (map[a][b - 2]!="B" && map[a][b - 2]!="W") {
                if (target[a][b]=="T") {
                    map[a][b - 1] = "H";
                    map[a][b] = "T";
                    map[a][b - 2] = "B";
                    y = b - 1;
                } else {
                    map[a][b - 1] = "H";
                    map[a][b] = "E";
                    map[a][b - 2] = "B";
                    y = b - 1;
                }
            }
        } else {
            /*if (target[a][b]=="T") {
                map[a][b - 1] = "H";
                map[a][b] = "T";
                y = b - 1;
            } else {
                map[a][b - 1] = "H";
                map[a][b] = "E";
                y = b - 1;
            }*/
            map[a][b - 1] = "H";
            map[a][b] = "E";
            y = b - 1;
        }
    }
}
void Game::moveDown(){
    //qDebug("moveDown");
    int a = x;
    int b = y;
    if (map[a][b + 1]!="W"&&map[a][b + 1]!="M") {
        if (map[a][b + 1]=="B") {
            if (map[a][b + 2]!="B" && map[a][b + 2]!="W") {
                if (target[a][b]=="T") {
                    map[a][b + 1] = "H";
                    map[a][b] = "T";
                    map[a][b + 2] = "B";
                    y = b - 1;
                } else {
                    map[a][b + 1] = "H";
                    map[a][b] = "E";
                    map[a][b + 2] = "B";
                    y = b + 1;
                }
            }
        } else {
            /*if (target[a][b]=="T") {
                map[a][b + 1] = "H";
                map[a][b] = "T";
                y = b + 1;
            } else {
                map[a][b + 1] = "H";
                map[a][b] = "E";
                y = b + 1;
            }*/
            map[a][b + 1] = "H";
            map[a][b] = "E";
            y = b + 1;
        }
    }
}
void Game::setBomb(){
    qDebug("setBomb");
    int a=x;
    int b=y;
    Delay_MSec(200);
    map[a][b]="B";
    Delay_MSec(2000);
    if (map[a+1][b]!="W")
    {
        map[a+1][b]="F";
    }
    if (map[a-1][b]!="W")
    {
        map[a-1][b]="F";
    }
    if (map[a][b+1]!="W")
    {
        map[a][b+1]="F";
    }
    if (map[a][b-1]!="W")
    {
        map[a][b-1]="F";
    }
    Delay_MSec(1000);
    if (map[a+1][b]=="F")
    {
        map[a+1][b]="E";
    }
    if (map[a-1][b]=="F")
    {
        map[a-1][b]="E";
    }
    if (map[a][b+1]=="F")
    {
        map[a][b+1]="E";
    }
    if (map[a][b-1]=="F")
    {
        map[a][b-1]="E";
    }
    map[a][b]="E";
}

void Game::setBomb1(){
    qDebug("setBomb1");
    bx=x;
    by=y;
    for(int i=0;i<200;i++){
        if (map[bx][by]!="E"){
            Delay_MSec(100);
        }
        else{
            map[bx][by]="B";
            break;
        }
    }
}
void Game::setBomb2(){
    qDebug("setBomb2");
    if (map[bx+1][by]!="W")
    {
        map[bx+1][by]="F";
    }
    if (map[bx-1][by]!="W")
    {
        map[bx-1][by]="F";
    }
    if (map[bx][by+1]!="W")
    {
        map[bx][by+1]="F";
    }
    if (map[bx][by-1]!="W")
    {
        map[bx][by-1]="F";
    }
}
void Game::setBomb2(int a,int b){
    if (map[a+1][b]!="W")
    {
        map[a+1][b]="F";
    }
    if (map[a-1][b]!="W")
    {
        map[a-1][b]="F";
    }
    if (map[a][b+1]!="W")
    {
        map[a][b+1]="F";
    }
    if (map[a][b-1]!="W")
    {
        map[a][b-1]="F";
    }
}
void Game::setBomb3(){
    qDebug("setBomb3");
    if (map[bx+1][by]=="F")
    {
        map[bx+1][by]="E";
    }
    if (map[bx-1][by]=="F")
    {
        map[bx-1][by]="E";
    }
    if (map[bx][by+1]=="F")
    {
        map[bx][by+1]="E";
    }
    if (map[bx][by-1]=="F")
    {
        map[bx][by-1]="E";
    }
    map[bx][by]="E";
    bx=0;
    by=0;
}
void Game::setBomb3(int a,int b){
    if (map[a+1][b]=="F")
    {
        map[a+1][b]="E";
    }
    if (map[a-1][b]=="F")
    {
        map[a-1][b]="E";
    }
    if (map[a][b+1]=="F")
    {
        map[a][b+1]="E";
    }
    if (map[a][b-1]=="F")
    {
        map[a][b-1]="E";
    }
    map[a][b]="E";
    Bx=0;
    By=0;
}
void Game::setMonsterMap(){
    //qDebug("setMonsterMap");
    float m=5.5;//m为wall2对路径难度的附加参数
    for (int i = 0; i < 19; i++){
        for(int j = 0; j < 19; j++){
            if(map[i][j]=="M"){
                monsterMap[i][j]=abs(i-x)+abs(j-y)+m;
            }
            else if(map[i][j]=="W"){
                monsterMap[i][j]=abs(i-x)+abs(j-y)+1000;
            }
            //else if(map[i][j]=="E"){monsterMap[i][j]=0;}
            else{
                monsterMap[i][j]=abs(i-x)+abs(j-y);
            }
        }
    }
    //qDebug("o");
}
void Game::monsterMove2(){
    int list1[4]={-1,0,1,0};
    int list2[4]={0,-1,0,1};
    int x1=0,y1=0;
    float value2=1000;
    for(int i=0;i<4;i++){
       int value=0;
       value=monsterMap[m1x+list1[i]][m1y+list2[i]];
       if(value<value2){
           value2=value;
           x1=m1x+list1[i];
           y1=m1y+list2[i];

       }
       else if(value==value2){
           x1=m1x+list1[i];
           y1=m1y+list2[i];
       }
    }
    map[m1x][m1y]="E";
    map[x1][y1]="S";
    m1x=x1;
    m1y=y1;
}
void Game::monsterMove(){
    //qDebug("monsterMove");
    int a=m1x;
    int b=m1y;
    if ((a==x-1&&b==y)||(a==x&&b==y-1)||(a==x+1&&b==y)||(a==x&&b==y+1)||(a==x&&b==y)){
        map[m1x][m1y]="E";
        map[x][y]="S";
        m1x=x;
        m1y=y;
        return;
    }
    /*if (m1x==fffm1x&&m1y==fffm1y&&(m1x%2==0)&&(m1y%2==0)){
        map[m1x][m1y]="E";
        map[fm1x][fm1y]="E";
        map[ffm1x][ffm1y]="E";
        return;
    }*/
    int x1=0,y1=0,x2=0,y2=0,x3=0,y3=0;
    float value2=1000;
       int submap[7][7]={{0,0,0,1,0,0,0},
                         {0,0,1,2,1,0,0},
                         {0,1,2,3,2,1,0},
                         {1,2,3,4,3,2,1},
                         {0,1,2,3,2,1,0},
                         {0,0,1,2,1,0,0},
                         {0,0,0,1,0,0,0}};
    int list2[4]={-1,0,1,0};
    int list1[4]={0,-1,0,1};
    for(int i=0;i<4;i++){
       int value=0;
       value=monsterMap[a+list1[i]][b+list2[i]];
       int v = value;
       for(int j=0;j<4;j++){
           value=v;
           if(submap[3+list1[i]+list1[j]][3+list2[i]+list2[j]]==2&&(a+list1[i]+list1[j])>0&&(a+list1[i]+list1[j])<18&&(b+list2[i]+list2[j])>0&&(b+list2[i]+list2[j])<18){
           //if(submap[3+list1[i]+list1[j]][3+list2[i]+list2[j]]==2){
               value=value+monsterMap[a+list1[i]+list1[j]][b+list2[i]+list2[j]];
           }
           else{
               continue;
           }
           int vv=value;
           for(int k=0;k<4;k++){
               value=vv;
               if(submap[3+list1[i]+list1[j]+list1[k]][3+list2[i]+list2[j]+list2[k]]==1&&(a+list1[i]+list1[j]+list1[k])>0&&(a+list1[i]+list1[j]+list1[k])<18&&(b+list2[i]+list2[j]+list2[k])>0&&(b+list2[i]+list2[j]+list2[k])<18){
               //if(submap[3+list1[i]+list1[j]+list1[k]][3+list2[i]+list2[j]+list2[k]]==1){
                   value=value+monsterMap[a+list1[i]+list1[j]+list1[k]][b+list2[i]+list2[j]+list2[k]];
               }
               else{
                   continue;
               }
               if(value<value2){
                   value2=value;
                   x1=a+list1[i];
                   y1=b+list2[i];
                   x2=a+list1[i]+list1[j];
                   y2=b+list2[i]+list2[j];
                   x3=a+list1[i]+list1[j]+list1[k];
                   y3=b+list2[i]+list2[j]+list2[k];

               }

               /*else if(value==value2){
                   int random=generateRandomInteger(0, 1);
                   if(random!=0){
                           x1=a+list1[i];
                           y1=b+list2[i];
                           x2=a+list1[i]+list1[j];
                           y2=b+list2[i]+list2[j];
                           x3=a+list1[i]+list1[j]+list1[k];
                           y3=b+list2[i]+list2[j]+list2[k];

                    }
               }*/

           }
       }
    }
    map[m1x][m1y]="E";
    map[x1][y1]="S";
    //m1x=x1;
    //m1y=y1;
    /*fffm1x=ffm1x;
    fffm1y=ffm1y;
    ffm1x=fm1x;
    ffm1y=fm1y;
    fm1x=m1x;
    fm1y=m1y;*/
    /*if ((a==x-1&&b==y)||(a==x&&b==y-1)||(a==x+1&&b==y)||(a==x&&b==y+1)||(a==x&&b==y)){
        map[m1x][m1y]="E";
        map[x][y]="S";
        m1x=x;
        m1y=y;
        return;
    }
    qDebug("step1");
    //Delay_MSec(2000);
    map[x2][y2]="S";
    map[x1][y1]="E";
    if ((a==x-1&&b==y)||(a==x&&b==y-1)||(a==x+1&&b==y)||(a==x&&b==y+1)||(a==x&&b==y)){
        map[m1x][m1y]="E";
        map[x][y]="S";
        m1x=x;
        m1y=y;
        return;
    }
    qDebug("step2");
    //loadMap(fileName);
    //Delay_MSec(2000);
    map[x3][y3]="S";
    map[x2][y2]="E";
    if ((a==x-1&&b==y)||(a==x&&b==y-1)||(a==x+1&&b==y)||(a==x&&b==y+1)||(a==x&&b==y)){
        map[m1x][m1y]="E";
        map[x][y]="S";
        m1x=x;
        m1y=y;
        return;
    }
    qDebug("step3");*/
    m1x=x1;
    m1y=y1;
    //loadMap(fileName);
    //Delay_MSec(2000);


}

bool Game::isEnd(){
    //qDebug("game over");
    int live=0;
    for (int i = 0; i < 19; i++)
        for (int j = 0; j < 19; j++) {
            if ((map[i][j]=="H")||(map[i][j]=="h")||(map[i][j]=="S"))
                live=live+1;

        }
    if (live!=1){
        return false;
    }
    return true;
    //return false;
}
void Game::draw(QPainter& painter){
    QImage image;
    for(int j=0;j<19;j++)
        for(int i=0;i<19;i++)
        {
            if(map[i][j]=="B")
            {
                image=bombImg;
            }else if(map[i][j]=="E")
            {
                image=emptyImg;
            }else if(map[i][j]=="H")
            {
                image=heroImg;
            }else if(map[i][j]=="N")
            {
                image=enemyImg;
            }else if(map[i][j]=="S")
            {
                image=monsterImg;
            }else if(map[i][j]=="T")
            {
                image=targetImg;
            }else if(map[i][j]=="W")
            {
                image=wallImg;
            }else if(map[i][j]=="M")
            {
                image=wallImg2;
            }else if(map[i][j]=="F")
            {
                image=fireImg;
            }
            painter.drawImage( 0+i*image.width(), 0+j*image.height(),image);
        }
}
void Game::Delay_MSec(unsigned int msec)
 {
     QEventLoop loop;//定义一个新的事件循环
     QTimer::singleShot(msec, &loop, SLOT(quit()));//创建单次定时器，槽函数为事件循环的退出函数
     loop.exec();//事件循环开始执行，程序会卡在这里，直到定时时间到，本循环被退出
 }

int Game::generateRandomInteger(int min, int max)
{
    Q_ASSERT(min < max);
    // 加入随机种子。种子是当前时间距离0点0分0秒的秒数。
    // 每次启动程序，只添加一次种子，以做到数字真正随机。
    static bool seedStatus;
    if (!seedStatus)
    {
        qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
        seedStatus = true;
    }
    int nRandom = qrand() % (max - min);
    nRandom = min + nRandom;

    return nRandom;
}
